package com.demo;

import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * <p>
 * <code>Person</code>
 * </p>
 *
 * @author junbao3
 * TODO
 * @date 2023-06-06 14:26
 * Copyright (C) 2021 IFlyTek. All rights reserved.
 */
public class Person {
    private int i = 0;
    private static  Unsafe unsafe;
    private static  long i_offset;
    static{
        /*
            @CallerSensitive
            public static Unsafe getUnsafe() {
                Class var0 = Reflection.getCallerClass();
                if (var0.getClassLoader() != null) {
                    throw new SecurityException("Unsafe");
                } else {
                    return theUnsafe;
                }
            }
        */
        //直接这样用会抛出异常 因为person类的类加载器是app，不为null
//        unsafe = Unsafe.getUnsafe();
        //Unsafe类有一个属性Unsafe theUnsafe，可以通过反射获取
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            unsafe = (Unsafe) field.get(null);
            i_offset = unsafe.objectFieldOffset(Person.class.getDeclaredField("i"));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        final Person person = new Person();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    //对象  对象某个属性的偏移量 属性在内存中期望值  属性在内存中更新值
                    boolean b = unsafe.compareAndSwapInt(person, i_offset, person.i, person.i + 1);
                    if (b){
                        //读属性在内存中的值
                        System.out.println(unsafe.getIntVolatile(person,i_offset));

                    }
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    boolean b =unsafe.compareAndSwapInt(person,i_offset,person.i,person.i+1);
                    if (b){
                        //读属性在内存中的值
                        System.out.println(unsafe.getIntVolatile(person,i_offset));

                    }
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}
/*
如果线程安全的，打印的i就不会重复
如果能直接操作内存里的数据，并发就不会有问题了
*/